#include "func_2th_parcel.h"
#include "shmem.h"
#include "msg_queue.h"

#define MAX_EPOLL 100000



//TCP服务端 
int main(void)
{
    int server_sockfd;//服务器套接字文件描述符
    int epfd;//监听树文件描述符
    struct epoll_event ready_array[MAX_EPOLL];//由于存放epoll返回的就绪结构体
    struct epoll_event node;//向监听树中放入的节点
    int ready_num;//处于就绪状态的套接字的数量
    int client_sockfd;//客户端套接字文件描述符
    char rw_buffer[1500];//读写缓冲区
    int flag;
    int recv_len = 68;//接受到的数据的长度
    int i;
    bzero(rw_buffer , sizeof(rw_buffer));//清空读写缓冲区
    server_sockfd = SOCKET_NET_CREATE("192.168.0.79" , 8888);//进行网络初始化
    //初始化epoll结构体
    node.data.fd = server_sockfd;
    node.events = EPOLLIN;//监听读事件
    pthread_mutex_t client_mutex=PTHREAD_MUTEX_INITIALIZER;//多线程初始化

    //注册信号处理函数
    void handle(int sig) {
    printf("recv sig: %d\n", sig);
    return;
}


//从消息队列中读取数据，然后发送给单片机
int read_msg_queue(){
	struct mymsgbuf buf;
	int msgid;	
	int ret;
    //获取消息队列表示号
	if((msgid = msgget(0x1234, 0666|IPC_CREAT)) < 0)	{
		fprintf(stderr, "open msg %X failed.\n", 0x1234);
		return;
	}
	while(strncmp(buf.ctext, "exit", 4))//当数据有回车时候，结束读取	
	{
		memset(&buf, 0, sizeof(buf));
		while((ret = msgrcv(msgid, &buf, sizeof(buf.ctext), buf.mtype, 0)) < 0)
		{
			if(errno == EINTR)	//当消息队列里此次数据读完，则返回继续读取下一次数据
				continue;
			return;		
		}		
		fprintf(stderr,"Msg:Type=%d,Len=%d,Text:%s",buf.mtype,ret, buf.ctext);
        SEND(ready_array[i].data.fd , buf.ctext , sizeof(buf.ctext) , MSG_NOSIGNAL);//把消息队列中的信息发送给客户端
	}
	return 0;
}


    signal(SIGPIPE, handle);

    //初始化监听树，并做错误处理
    if((epfd = epoll_create(MAX_EPOLL)) == -1)
    {
    	perror("epoll_create call failed\n");
    	exit(-1);
    }
    //向监听树中添加服务器套接字结构体，并做错误处理
    if((epoll_ctl(epfd , EPOLL_CTL_ADD , server_sockfd , &node)) == -1)
    {
    	perror("epoll_ctl call failed\n");
    	exit(-1);
    }
    printf("epoll_server wait TCP connect\n");



    //创建子线程
    pthread_t tid;
    pthread_create(&tid, NULL, read_msg_queue, NULL);

    while(1)
    {
    	//获取处于就绪状态的套接字数量
        if((ready_num = epoll_wait(epfd , ready_array , MAX_EPOLL , -1)) == -1)
        {
            perror("epoll_wait call failed\n");
            exit(0);
        }
        i = 0;
        while(ready_num)
        {
            //辨别就绪，如果是服务端套接字就绪
            if(ready_array[i].data.fd == server_sockfd)
            {
                client_sockfd = SERVER_ACCEPTING(ready_array[i].data.fd);//与客户端建立TCP链接
                node.data.fd = client_sockfd;
                if(epoll_ctl(epfd , EPOLL_CTL_ADD , client_sockfd , &node) == -1)
                {
                	perror("epoll_ctl failed\n");
                	exit(-1);
                }
            }
            //如果是客户端套接字就绪
            else
            {  
                recv_len = RECV(ready_array[i].data.fd , rw_buffer , sizeof(rw_buffer) , 0);
                flag = 0;
                //如果recv_len = 0,就说明与客户端套接字对应的客户端退出了，将对应客户端套接字移出套接字存储数组与监听集合
                if(recv_len == 0)
                {
                    perror("某一客户端与本服务器断开链接\n");
                    printf("客户端%d 与本服务器断开链接，关闭其对应的套接字并停止监听\n" , ready_array[i].data.fd);
                    //关闭该套接字
                    close(ready_array[i].data.fd);
                    //将其对应的节点从监听树上摘下来
                    epoll_ctl(epfd , EPOLL_CTL_DEL , ready_array[i].data.fd , NULL);
                }
                //进行业务处理：小写字母转大写字母
                printf("服务器已接收到客户端%d 发来的信息 : %s，现在对其进行处理\n" , ready_array[i].data.fd , rw_buffer);
                while(recv_len > flag)
                {
                    rw_buffer[flag] = toupper(rw_buffer[flag]);
                    flag++;
                }

                
                printf("服务器已对客户端%d 发来的信息完成处理，处理后的数据为 : %s\n",ready_array[i].data.fd , rw_buffer);
                printf("写入共享内存:");

                static struct shm_param para;

                 struct shm_data
                 {
                  char data[68];
                   };

                    int ret=1;

                ret =shm_init(&para,"TCP_MYQTT",1024);
                if(ret<0)
                {
                   return -1;
                   }

               struct shm_data *addr=(struct shm_data*)shm_getaddr(&para);
               if(addr==NULL)
               {
                 return -1;
                 }

               strcpy(addr->data,rw_buffer);//把单片机发来的数据写入共享内存

               // write_shm(rw_buffer);  //把单片机发来的消息写入共享内存
                //SEND(ready_array[i].data.fd , addr->data , recv_len , MSG_NOSIGNAL);//发送信息给客户端
                //bzero(rw_buffer , sizeof(rw_buffer));  //清空读写缓冲区
                read_shm();//读取共享内存中的数据
                recv_len = 0;
            }
            ready_num--;
            i++;
        }
    }
    close(server_sockfd);   //关闭服务端的套接字
    printf("server shutdown\n");
    return 0;
}